package com.probox.common.entity.service.order.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import com.probox.common.core.constant.CachePrefix;
import com.probox.common.core.constant.MessageConstants;
import com.probox.common.core.enums.*;
import com.probox.common.core.exception.BaseException;
import com.probox.common.core.text.Convert;
import com.probox.common.core.utils.DateUtils;
import com.probox.common.core.utils.SecurityUtils;
import com.probox.common.core.utils.StringUtils;
import com.probox.common.redis.service.RedisService;
import com.probox.customer.api.domain.*;
import com.probox.common.entity.domain.customer.CustomerAddress;
import com.probox.common.entity.domain.order.*;
import com.probox.common.entity.service.customer.ICustomerAddressService;
import com.probox.common.entity.service.customer.ICustomerFundService;
import com.probox.common.entity.service.customer.ICustomerInfoService;
import com.probox.common.entity.service.platfom.IPlatformAddressService;
import com.probox.common.entity.service.platfom.IPlatformGeneralsettingsService;
import com.probox.order.api.domain.*;
import com.probox.order.api.utils.WechatV3Payment;
import com.probox.common.entity.service.order.*;
import com.probox.common.entity.domain.order.vo.PostSaleQuery;
import com.probox.platform.api.domain.PlatformAddressVo;
import com.probox.platform.api.domain.PlatformGeneralsettingsVo;
import com.probox.product.api.domain.ProductOptVo;
import com.probox.supplier.api.domain.SupplierAddressVo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.probox.common.entity.mapper.order.OrderPostSaleMapper;
import org.springframework.transaction.annotation.Transactional;

/**
 * 订单售后Service业务层处理
 *
 * @author hds
 * @date 2021-06-07
 */
@Service
@Transactional
public class OrderPostSaleServiceImpl extends ServiceImpl<OrderPostSaleMapper, OrderPostSale> implements IOrderPostSaleService {

    //用户操作限制
    private static final int USER_OPERATOR_LIMIT = 1;
    private static final int USER_OPERATOR_LIMIT_TIME = 3;

    //订单售后缓存
    private static final String ORDER_POST_SALE_KEY = CachePrefix.PRE_GLOABLE + "ORDER_POST_SALE_";
    private static final String ORDER_POST_SALE_ITEM_KEY = CachePrefix.PRE_GLOABLE + "ORDER_POST_SALE_ITEM_";

    private static final Logger log = LoggerFactory.getLogger(OrderPostSaleServiceImpl.class);

    @Autowired
    private OrderPostSaleMapper orderPostSaleMapper;

    @Autowired
    private IOrderInfoItemService itemService;


    @Autowired
    private ICustomerInfoService iCustomerInfoService;

    @Autowired
    private IOrderInfoService orderInfoService;

    @Autowired
    private RedisService redisService;

    @Autowired
    private IOrderPayBackService payBackService;

    @Autowired
    private IOrderPostSaleNodeService saleNodeService;

    @Autowired
    private IOrderInfoParentService parentService;

    @Autowired
    private IOrderPayInfoService payInfoService;

    @Autowired
    private IPlatformAddressService platformAddressService;

    @Autowired
    private IPlatformGeneralsettingsService platformGeneralsettingsService;


    @Autowired
    private ICustomerFundService iCustomerFundService;

    @Autowired
    private ICustomerAddressService iCustomerAddressService;

    /**
     * 查询订单售后
     *
     * @param serviceUid 订单售后ID
     * @return 订单售后
     */
    @Override
    public OrderPostSaleVo selectOrderServiceById(Long serviceUid) {
        OrderPostSaleVo vo = null;
        OrderPostSale sale = this.getById(serviceUid);
        if (sale != null) {
            vo = new OrderPostSaleVo();
            BeanUtils.copyProperties(sale, vo);
            //订单明细信息
            if (vo.getItemUid() != null && vo.getItemUid() > 0) {
                OrderItemVo itemVo = null;
                OrderInfoItem item = itemService.getById(vo.getItemUid());
                if (item != null) {
                    itemVo = new OrderItemVo();
                    BeanUtils.copyProperties(item, itemVo);
                    vo.setItemVo(itemVo);
                }
            }
            //地址信息
            getAddress(vo);
        }

        return vo;
    }

    /**
     * 查询订单售后列表
     *
     * @param orderPostSale 订单售后
     * @return 订单售后
     */
    @Override
    public List<OrderPostSale> queryList(OrderPostSale orderPostSale) {
        QueryWrapper<OrderPostSale> queryWrapper = Wrappers.query();
        if (StringUtils.isNotEmpty(String.valueOf(orderPostSale.getServiceUid())) && orderPostSale.getServiceUid() != null) {
            queryWrapper.eq("SERVICE_UID", orderPostSale.getServiceUid());
        }
        if (StringUtils.isNotEmpty(String.valueOf(orderPostSale.getOrderUid())) && orderPostSale.getOrderUid() != null) {
            queryWrapper.eq("ORDER_UID", orderPostSale.getOrderUid());
        }
        if (StringUtils.isNotEmpty(String.valueOf(orderPostSale.getOrderNo())) && orderPostSale.getOrderNo() != null) {
            queryWrapper.like("ORDER_NO", orderPostSale.getOrderNo());
        }
        if (StringUtils.isNotEmpty(String.valueOf(orderPostSale.getItemUid())) && orderPostSale.getItemUid() != null) {
            queryWrapper.eq("ITEM_UID", orderPostSale.getItemUid());
        }
        if (StringUtils.isNotEmpty(String.valueOf(orderPostSale.getSupplierUid())) && orderPostSale.getSupplierUid() != null) {
            queryWrapper.eq("SUPPLIER_UID", orderPostSale.getSupplierUid());
        }
        if (StringUtils.isNotEmpty(String.valueOf(orderPostSale.getSupplierName())) && orderPostSale.getSupplierName() != null) {
            queryWrapper.like("SUPPLIER_NAME", orderPostSale.getSupplierName());
        }
        if (StringUtils.isNotEmpty(String.valueOf(orderPostSale.getServiceType())) && orderPostSale.getServiceType() != null) {
            queryWrapper.eq("SERVICE_TYPE", orderPostSale.getServiceType());
        }
        if (StringUtils.isNotEmpty(String.valueOf(orderPostSale.getServiceReason())) && orderPostSale.getServiceReason() != null) {
            queryWrapper.eq("SERVICE_REASON", orderPostSale.getServiceReason());
        }
        if (StringUtils.isNotEmpty(String.valueOf(orderPostSale.getDataStatus())) && orderPostSale.getDataStatus() != null) {
            queryWrapper.eq("DATA_STATUS", orderPostSale.getDataStatus());
        }
        if (StringUtils.isNotEmpty(String.valueOf(orderPostSale.getApplyUid())) && orderPostSale.getApplyUid() != null) {
            queryWrapper.eq("APPLY_UID", orderPostSale.getApplyUid());
        }
        if (StringUtils.isNotEmpty(String.valueOf(orderPostSale.getApplyNickName())) && orderPostSale.getApplyNickName() != null) {
            queryWrapper.eq("APPLY_NICK_NAME", orderPostSale.getApplyNickName());
        }
        if (StringUtils.isNotEmpty(String.valueOf(orderPostSale.getApplyPhone())) && orderPostSale.getApplyPhone() != null) {
            queryWrapper.like("APPLY_PHONE", orderPostSale.getApplyPhone());
        }
        if (orderPostSale.getApplyTimeArray() != null && orderPostSale.getApplyTimeArray().size() > 0) {
            queryWrapper.ge("APPLY_TIME", orderPostSale.getApplyTimeArray().get(0));
            if (orderPostSale.getApplyTimeArray().size() > 1)
                queryWrapper.le("APPLY_TIME", orderPostSale.getApplyTimeArray().get(1) + " 23:59:59");
        }
        queryWrapper.orderByDesc("UPDATE_TIME");

        Long platFormUid = SecurityUtils.getPlatformId();
        if (platFormUid != null && platFormUid > 0)
            queryWrapper.eq("PLATFORM_UID", platFormUid);
        else
            throw new BaseException("账号异常");

        Long supplierId = SecurityUtils.getSupplierId();
        if (supplierId != null && supplierId > 0)
            queryWrapper.eq("SUPPLIER_UID", supplierId);

        List<OrderPostSale> saleList = orderPostSaleMapper.selectList(queryWrapper);
        if (ObjectUtil.isNotEmpty(saleList)) {
            for (OrderPostSale sale : saleList) {
                if (ObjectUtil.isNotEmpty(sale.getItemUid())) {
                    sale.setItem(itemService.getById(sale.getItemUid()));
                }
            }
        }

        return saleList;
    }

    /**
     * 新增订单售后
     *
     * @param orderPostSale 订单售后
     * @return 结果
     */
    @Override
    public boolean insertOrderService(OrderPostSale orderPostSale) {

        return this.save(orderPostSale);

    }

    /**
     * 受理 + 收货完结
     *
     * @param orderPostSale 订单售后
     * @return 结果
     */
    @Override
    
    public boolean updateOrderService(OrderPostSale orderPostSale) {
        String key = ORDER_POST_SALE_KEY + orderPostSale.getServiceUid();
        limitUserOperation(key);

        if (ObjectUtil.isEmpty(orderPostSale.getServiceUid()))
            throw new BaseException("售后ID不能为空");

        OrderPostSale sale = this.getById(orderPostSale.getServiceUid());
        if (sale == null) throw new BaseException("没有找到售后信息");

        Date date = DateUtil.date();
        Long accountUid = SecurityUtils.getUserId();
        String accountName = SecurityUtils.getUsername();
        sale.setUpdateUser(accountUid);
        sale.setUpdateName(accountName);
        sale.setUpdateTime(date);
        sale.setDataStatus(orderPostSale.getDataStatus());
        //收货完结
        if (ServiceStatusEnum.success.getKey().equals(sale.getDataStatus())) {

            String type = ProductOptType.refund.getKey();
            OrderInfo orderInfo = orderInfoService.getById(sale.getOrderUid());
            if (orderInfo == null) throw new BaseException("没有找到订单信息");

            OrderInfoItem item = itemService.getById(sale.getItemUid());
            if (item != null) {
                sale.setItem(item);
                //退货退款
                if (ServiceTypeEnum.returnd.getKey().equals(sale.getServiceType())) {

                    OrderInfoParent parent = parentService.getOrderInfo(orderInfo.getParentOrderNo());
                    if (parent == null) throw new BaseException("没有找到订单支付信息");
                    //微信退款=========================
                    startRefund(sale, orderInfo, parent);

                } else if (ServiceTypeEnum.change.getKey().equals(sale.getServiceType())) {
                    type = ProductOptType.barter.getKey();
                }

                //完结
                itemService.finishSale(sale.getItemUid());
                //退款数日志
                orderInfoService.sendLogMsg(type, orderInfo.getPlatformUid(), orderInfo.getCustomerUid(),item.getOrderType(), item.getProUid(), Convert.toLong(sale.getServiceNumber()));
            } else
                throw new BaseException("没有找到订单商品信息！");
        }
        //记录流程节点
        saveSaleNode(sale.getServiceUid(), sale.getDataStatus(),
                "商家：" + accountName + "," + ServiceStatusEnum.getNameByKey(sale.getDataStatus()),
                accountUid, accountName, date);

        return this.updateById(sale);
    }

    /**
     * 批量删除订单售后
     *
     * @param serviceUids 需要删除的订单售后ID
     * @return 结果
     */
    @Override
    public boolean deleteOrderServiceByIds(Long[] serviceUids) {
        return this.removeByIds(Arrays.asList(serviceUids));
    }


    /**
     * 查询售后列表
     *
     * @param query
     * @return
     */
    @Override
    public List<OrderPostSaleVo> getPostSaleList(PostSaleQuery query) {
        List<OrderPostSaleVo> saleVoList = queryStatus(query);
        if (saleVoList != null && saleVoList.size() > 0) {
            OrderItemVo itemVo = null;

            for (OrderPostSaleVo vo : saleVoList) {
                //订单明细信息
                if (vo.getItemUid() != null && vo.getItemUid() > 0) {
                    OrderInfoItem item = itemService.getById(vo.getItemUid());
                    if (item != null) {
                        itemVo = new OrderItemVo();
                        BeanUtils.copyProperties(item, itemVo);
                        vo.setItemVo(itemVo);
                    }
                }
                //前端列表不需要地址明细
                if (ObjectUtil.isEmpty(query.getApplyUid())) {
                    getAddress(vo);
                }
            }
        }

        return saleVoList;
    }

    private List<OrderPostSaleVo> queryStatus(PostSaleQuery query) {
        List<String> list = new ArrayList<>();
        log.info("\n========售后列表查询参数：{}======", JSON.toJSONString(query));
        if (ObjectUtil.isNotEmpty(query)) {
            if ("0".equals(query.getQueryStatus())) {
                list.add(ServiceStatusEnum.apply.getKey());
                list.add(ServiceStatusEnum.processing.getKey());
                list.add(ServiceStatusEnum.agree.getKey());
                list.add(ServiceStatusEnum.refuse.getKey());
            } else if ("1".equals(query.getQueryStatus())) {
                list.add(ServiceStatusEnum.success.getKey());
            }
            log.info("\n========售后列表状态参数封装：{}======", JSON.toJSONString(list));
            return orderPostSaleMapper.getPostSale(query, list);
        } else
            throw new BaseException("缺少售后状态参数！");
    }

    /**
     * 获取客户，供应商或平台收货地址
     *
     * @param vo
     */
    private void getAddress(OrderPostSaleVo vo) {
        //客户收货地址
        if (vo.getCustomerAddressUid() != null && vo.getCustomerAddressUid() > 0) {
            CustomerAddressVo customerAddressVo = null;
            CustomerAddress byId = iCustomerAddressService.getById(vo.getCustomerAddressUid());
            if (ObjectUtil.isNotEmpty(byId)) {
                customerAddressVo = new CustomerAddressVo();
                BeanUtils.copyProperties(byId, customerAddressVo);
            }
            vo.setCustomerAddressVo(customerAddressVo);
        }

        //供应商,平台收货地址
        if (ObjectUtil.isNotEmpty(vo.getSupplierAddressUid())) {
            if (vo.getSupplierUid() != null && vo.getSupplierUid() > 0) {

            } else {
                PlatformAddressVo addressVo = new PlatformAddressVo();
                addressVo.setPlatformAddressUid(vo.getSupplierAddressUid());
                PlatformAddressVo platformAddressVo = platformAddressService.getAddress(addressVo);
                if (platformAddressVo != null)
                    vo.setPlatformAddressVo(platformAddressVo);
            }
        }
    }

    @Override
    public int getPostSaleCount(PostSaleQuery query) {
        List<OrderPostSaleVo> saleVoList = queryStatus(query);
        if (ObjectUtil.isNotEmpty(saleVoList))
            return saleVoList.size();
        return 0;
    }

    /**
     * 售后详情
     *
     * @param itemId
     * @return
     */
    @Override
    public OrderPostSaleVo getPostSaleDetail(Long itemId) {
        if (ObjectUtil.isEmpty(itemId))
            throw new BaseException("订单明细ID不能为空");

        OrderInfoItem item = itemService.getById(itemId);
        if (item == null) throw new BaseException("没有找到订单信息");

        OrderInfo orderInfo = orderInfoService.getById(item.getOrderUid());
        if (orderInfo == null) throw new BaseException("没有找到订单信息");

        OrderPostSaleVo vo = new OrderPostSaleVo();
        ;
        vo.setSupplierUid(item.getSupplierUid());
        vo.setPlatformUid(orderInfo.getPlatformUid());
        vo.setApplyUid(SecurityUtils.getCustomerUid());

        QueryWrapper<OrderPostSale> queryWrapper = Wrappers.query();
        queryWrapper.eq("ITEM_UID", itemId);
        queryWrapper.eq("APPLY_UID", vo.getApplyUid());
        List<OrderPostSale> postSaleList = orderPostSaleMapper.selectList(queryWrapper);

        //正在售后的，返回售后信息
        if (ObjectUtil.isNotEmpty(postSaleList)) {
            OrderPostSale postSale = postSaleList.get(0);
            BeanUtils.copyProperties(postSale, vo);

            //订单明细信息
            OrderItemVo itemVo = null;
            if (item != null) {
                itemVo = new OrderItemVo();
                BeanUtils.copyProperties(item, itemVo);
                vo.setItemVo(itemVo);
            }
        }

        //可申请的售后类型
        if (SaleStatusEnum.normal.getKey().equals(item.getSaleStatus())) {
            List<ServiceTypeVo> list = new ArrayList<ServiceTypeVo>();


            if (ObjectUtil.isNotEmpty(orderInfo)) {
                if (orderInfo.getOrderType().equals(ActivityTypeEnum.bargain.getKey())) {
                    list.add(new ServiceTypeVo(SaleServiceTypeEnum.change.getKey(), SaleServiceTypeEnum.change.getValue(), SaleServiceTypeEnum.change.getDesc()));
                } else {
                    if (SendStatusEnum.unShip.getKey().equals(orderInfo.getSendStatus())) {
                        list.add(new ServiceTypeVo(SaleServiceTypeEnum.refund.getKey(), SaleServiceTypeEnum.refund.getValue(), SaleServiceTypeEnum.refund.getDesc()));
                    } else if (SendStatusEnum.ship.getKey().equals(orderInfo.getSendStatus())) {
                        list.add(new ServiceTypeVo(SaleServiceTypeEnum.retreat.getKey(), SaleServiceTypeEnum.retreat.getValue(), SaleServiceTypeEnum.retreat.getDesc()));
                    } else {
                        list.add(new ServiceTypeVo(SaleServiceTypeEnum.retreat.getKey(), SaleServiceTypeEnum.retreat.getValue(), SaleServiceTypeEnum.retreat.getDesc()));
                        list.add(new ServiceTypeVo(SaleServiceTypeEnum.change.getKey(), SaleServiceTypeEnum.change.getValue(), SaleServiceTypeEnum.change.getDesc()));
                    }
                }
                vo.setServiceTypeVoList(list);

                //获取供应商或者平台的默认收货地址
                if (item.getSupplierUid() != null && item.getSupplierUid() > 0) {

                } else {
                    PlatformAddressVo addressVo = new PlatformAddressVo();
                    addressVo.setPlatformUid(orderInfo.getPlatformUid());
                    addressVo.setIsDefault(AddressDefault.tolerant.getKey());
                    addressVo.setDataType(SupplierAddressType.receive.getKey());
                    PlatformAddressVo platformAddressVo = platformAddressService.getAddress(addressVo);
                    if (platformAddressVo != null) vo.setPlatformAddressVo(platformAddressVo);
                }

                //售后说明，前端从平台信息中取
            }

        } else {
            getAddress(vo);
        }
        return vo;
    }

    /**
     * 申请售后
     *
     * @param vo
     * @return
     */
    @Override
    public boolean applyPostSale(OrderPostSaleVo vo) {
        if (ObjectUtil.isEmpty(vo.getItemUid()))
            throw new BaseException("售后订单ID为空");

        String key = ORDER_POST_SALE_ITEM_KEY + vo.getItemUid();
        limitUserOperation(key);

        OrderInfoItem item = itemService.getById(vo.getItemUid());
        OrderInfo orderInfo = orderInfoService.getById(item.getOrderUid());
        if (item != null && orderInfo != null) {
            vo.setSupplierUid(item.getSupplierUid());

            OrderPostSale postSale = new OrderPostSale();
            postSale.setSupplierUid(vo.getSupplierUid());
            postSale.setSupplierName(orderInfo.getSupplierName());
            //商家，平台收货地址
            if (vo.getSupplierUid() != null && vo.getSupplierUid() > 0) {

            } else {
                PlatformAddressVo addressVo = new PlatformAddressVo();
                addressVo.setPlatformUid(vo.getPlatformUid());
                addressVo.setIsDefault(AddressDefault.tolerant.getKey());
                addressVo.setDataType(SupplierAddressType.receive.getKey());
                PlatformAddressVo platformAddressVo = platformAddressService.getAddress(addressVo);
                if (platformAddressVo != null)
                    postSale.setSupplierAddressUid(platformAddressVo.getPlatformAddressUid());
                else
                    throw new BaseException("没有找到商家收货地址，不能售后");
            }

            if (SaleStatusEnum.normal.getKey().equals(item.getSaleStatus())) {
                //换货==============
                if (SaleServiceTypeEnum.change.getKey().equals(vo.getServiceType())) {
                    CustomerAddressVo customerAddressVo = null;
                    if (vo.getCustomerAddressUid() != null && vo.getCustomerAddressUid() > 0) {
                        CustomerAddress byId = iCustomerAddressService.getById(vo.getCustomerAddressUid());
                        if (ObjectUtil.isNotEmpty(byId)) {
                            customerAddressVo = new CustomerAddressVo();
                            BeanUtils.copyProperties(byId, customerAddressVo);
                        }
                        if (customerAddressVo == null) throw new BaseException("没有找到收货地址信息");
                    } else {
                        throw new BaseException("请提供收货地址信息");
                    }
                    postSale.setCustomerAddressUid(customerAddressVo.getAddressUid());

                    //退货退款================
                } else if (SendStatusEnum.receive.getKey().equals(orderInfo.getSendStatus())
                        && SaleServiceTypeEnum.retreat.getKey().equals(vo.getServiceType())) {
                    //收货后多长时间内解冻，解冻后不能售后(退货退款)，店铺配置处理
                    PlatformGeneralsettingsVo generalsettingsVo = platformGeneralsettingsService.get(vo.getPlatformUid());
                    if (ObjectUtil.isNotEmpty(generalsettingsVo)) {
                        Date expire = DateUtils.addDay(orderInfo.getReceiveTime(), Integer.parseInt(generalsettingsVo.getOrderMoney()));
                        if (System.currentTimeMillis() > expire.getTime())
                            throw new BaseException("已超出此订单可申请售后时间");
                    }
                }

                Date now = new Date();
                postSale.setPlatformUid(vo.getPlatformUid());
                postSale.setOrderUid(orderInfo.getOrderUid());
                postSale.setOrderNo(orderInfo.getOrderNo());
                postSale.setItemUid(vo.getItemUid());
                postSale.setServiceType(vo.getServiceType());
                postSale.setServiceReason(vo.getServiceReason());
                postSale.setServiceNumber(item.getItemNumber().intValue());
                postSale.setServiceAmount(item.getItemAmount());
                postSale.setServiceCash(item.getPayAmount());
                postSale.setServiceBalance(item.getPayByBalance());
                postSale.setProofImages(vo.getProofImages());
                postSale.setProofDesc(vo.getProofDesc());
                postSale.setDataStatus(ServiceStatusEnum.apply.getKey());
                postSale.setApplyUid(orderInfo.getCustomerUid());
                postSale.setApplyNickName(orderInfo.getCustomerName());
                postSale.setApplyPhone(vo.getApplyPhone());
                postSale.setApplyTime(now);
                postSale.setCustomerAddressUid(vo.getCustomerAddressUid());
                postSale.setRemark(vo.getRemark());
                postSale.setUpdateUser(SecurityUtils.getCustomerUid());
                postSale.setUpdateName(SecurityUtils.getCustomerUserName());
                postSale.setUpdateTime(now);
                if (this.save(postSale)) {
                    itemService.updateSaleStateToServer(vo.getItemUid());
                    saveSaleNode(postSale.getServiceUid(), postSale.getDataStatus(), "用户：" + postSale.getUpdateName() + " 申请售后",
                            postSale.getUpdateUser(), postSale.getUpdateName(), now);
                }
                return true;
            } else {
                throw new BaseException("该订单已在售后中，请勿重复提交");
            }
        } else throw new BaseException("没有找到售后订单信息");
    }


    /**
     * 取消售后
     *
     * @param itemId
     * @return
     */
    @Override
    public boolean cancelPostSale(Long itemId) {
        if (ObjectUtil.isEmpty(itemId))
            throw new BaseException("售后订单ID为空");

        String key = ORDER_POST_SALE_ITEM_KEY + itemId;
        limitUserOperation(key);

        OrderInfoItem item = itemService.getById(itemId);
        OrderInfo orderInfo = orderInfoService.getById(item.getOrderUid());
        if (item != null && orderInfo != null) {
            if (SaleStatusEnum.apply.getKey().equals(item.getSaleStatus())) {
                QueryWrapper<OrderPostSale> queryWrapper = Wrappers.query();
                List<String> status = new ArrayList<String>();
                status.add(ServiceStatusEnum.processing.getKey());
                status.add(ServiceStatusEnum.agree.getKey());
                queryWrapper.in("DATA_STATUS", status);
                queryWrapper.eq("ITEM_UID", itemId);
                queryWrapper.orderByDesc("SERVICE_UID");

                List<OrderPostSale> saleList = orderPostSaleMapper.selectList(queryWrapper);
                if (ObjectUtil.isNotEmpty(saleList)) {
                    OrderPostSale postSale = saleList.get(0);
                    postSale.setDataStatus(ServiceStatusEnum.cancel.getKey());
                    if (this.updateById(postSale)) {
                        //恢复售后状态正常
                        itemService.cancelSaleState(itemId);
                        saveSaleNode(postSale.getServiceUid(), postSale.getDataStatus(), "用户：" + postSale.getUpdateName() + " 取消了售后",
                                postSale.getUpdateUser(), postSale.getUpdateName(), new Date());
                    }
                } else
                    throw new BaseException("该订单不能取消售后");
            } else
                throw new BaseException("该订单不能取消售后");
        } else
            throw new BaseException("没有找到售后订单信息");

        return true;
    }

    /**
     * 微信退款，已支付订单取消或订单售后退款
     *
     * @param parent
     * @param orderInfo
     * @param sale
     * @param subMchid
     * @return
     */
    public boolean wechatRefund(OrderInfoParent parent, OrderInfo orderInfo, OrderPostSale sale, String subMchid) {
        //商户退款单号
        String refundNo = parent.getParentOrderNo() + System.currentTimeMillis();
        //实际退款金额
        Long refundAmount = orderInfo.getPayAmount();
        if (sale != null && sale.getServiceCash() != null) {
            refundAmount = sale.getServiceCash();

            //订单已退款金额
            Long backAmount = payBackService.sumBackByOrderNo(orderInfo.getOrderNo());
            if (orderInfo.getPayAmount() - backAmount < refundAmount) {
                log.info("订单编号：{}，已经没有可退金额", orderInfo.getOrderNo());
                return false;
            }
        }


        WxPayRequestBo wxPayRequestBo = new WxPayRequestBo()
                .setMchid(subMchid)
                .setOut_refund_no(refundNo)
                .setOut_trade_no(parent.getParentOrderNo())
                .setAmount(new WxPaymentAmount(parent.getPayAmount(), refundAmount));
        String wxRefundRequestJsonStr = JSONUtil.toJsonStr(wxPayRequestBo);
        try {
            //V3微信退款
            WxRefundVo wxRefundVo = WechatV3Payment.V3ApplyRefund(wxRefundRequestJsonStr);
            if (wxRefundVo != null &&
                    ("SUCCESS".equals(wxRefundVo.getStatus()) || "PROCESSING".equals(wxRefundVo.getStatus()))) {
                OrderPayBack back = new OrderPayBack();
                back.setCustomerUid(orderInfo.getCustomerUid());
                back.setCustomerName(orderInfo.getCustomerName());
                back.setOrderNo(orderInfo.getOrderNo());
                back.setOrderUid(orderInfo.getOrderUid());
                back.setPayAmount(parent.getPayAmount());
                back.setBackAmount(orderInfo.getPayAmount());
                back.setBackReason("取消订单");
                if (sale != null) {
                    back.setItemUid(sale.getItemUid());
                    back.setBackAmount(sale.getServiceCash());
                    back.setApplyReason(sale.getServiceReason());
                    back.setBackReason("售后退款");
                    back.setAuditRemark(sale.getRemark());
                }
                back.setApplyTime(new Date());
                back.setStatus(DataStatus.valid.getKey());
                back.setConfirmTime(back.getApplyTime());
                back.setBackStatus(BackStatusEnum.success.getKey());
                back.setRefundId(wxRefundVo.getRefund_id());
                back.setBackType(BackTypeEnum.wechat.getKey());

                //退分润，积分，余额等，订单取消时，sale为空
                refundCustomerFund(parent, orderInfo, sale, refundAmount);

                return payBackService.save(back);
            }
            return false;
        } catch (Exception e) {
            e.printStackTrace();
            throw new BaseException(e.getMessage());
        }
    }

    /**
     * 退分润，积分，余额等
     */
    @Override
    public void refundCustomerFund(OrderInfoParent parent, OrderInfo orderInfo, OrderPostSale sale, Long refundAmount) {
        log.info("\n============订单退款开始计算需扣除分润，积分，余额等=============\n");
        Long customerId = parent.getCustomerId();
        CustomerVo customerVo = iCustomerInfoService.getCustomerVo(customerId);
        CustomerVo father = null;
        CustomerVo grandFather = null;
        if (ObjectUtil.isNotEmpty(customerVo)) {
            if (customerVo.getFatherUid() != null) {
                father = iCustomerInfoService.getCustomerVo(customerVo.getFatherUid());
            }
            if (customerVo.getGrandFatherUid() != null) {
                grandFather = iCustomerInfoService.getCustomerVo(customerVo.getFatherUid());
            }
        }

        giveProfit(customerVo, 0, customerId, orderInfo, sale, refundAmount);
        giveProfit(father, 1, customerId, orderInfo, sale, refundAmount);
        giveProfit(grandFather, 2, customerId, orderInfo, sale, refundAmount);

    }

    /**
     * 计算退款金额的分润,积分
     *
     * @param customer
     * @param level
     * @param fromUserId
     * @return
     */
    private boolean giveProfit(CustomerVo customer, int level, Long fromUserId,
                               OrderInfo orderInfo, OrderPostSale sale, Long refundAmount) {
        if (customer == null || customer.getCustomerLevelVo() == null) {
            return false;
        }
        log.info("\n===========退分润计算，客户:{}===========\n", customer);
        Date date = new Date();
        Long profitRate = 0L;
        if (level == 0) {
            profitRate = Convert.toLong(customer.getCustomerLevelVo().getSelfbuyPointsPointsStr(), 0L);
            log.info("\n===========自购分润计算，分润比例:{}===========\n", profitRate);

            //售后退退余额
            if (sale != null && ObjectUtil.isNotEmpty(sale.getServiceBalance())) {
                CustomerFundVo fundVo = new CustomerFundVo();
                fundVo.setPlatformUid(customer.getPlatformUid());
                fundVo.setBizTime(date);
                fundVo.setBizNo(orderInfo.getOrderNo());
                fundVo.setOrderUid(orderInfo.getOrderUid());
                fundVo.setItemUid(sale.getItemUid());
                fundVo.setFromCustomerId(fromUserId);
                fundVo.setCustomerUid(customer.getCustomerUid());
                fundVo.setBalance(sale.getServiceBalance());
                fundVo.setRemark("订单退款:" + sale.getItem().getProName());
                fundVo.setStatus(CustomerFundStatusEnum.valid.getKey());
                log.info("\n===========退款退余额，增加资金参数:{}===========\n", fundVo);
                int i = iCustomerFundService.addCustomerFund(fundVo);
                log.info("\n===========退款退余额，增加资金结果:{}===========\n", JSON.toJSONString(i));
            }

        } else if (level == 1) {
            profitRate = Convert.toLong(customer.getCustomerLevelVo().getDirectPointsPointsStr(), 0L);
            log.info("\n===========直接分润计算，分润比例:{}===========\n", profitRate);
        } else if (level == 2) {
            profitRate = Convert.toLong(customer.getCustomerLevelVo().getIndirectPointsPointsStr(), 0L);
            log.info("\n===========间接分润计算，分润比例:{}===========\n", profitRate);
        }
        //积分倍数可能是小数
        double score = 0L;
        List<CustomerLevelPrivleageVo> lpList = customer.getCustomerLevelVo().getCustomerLevelPrivleageVos();
        for (CustomerLevelPrivleageVo pv : lpList) {
            if (CustomerLevelPrivilegeEnum.multiplePoints.getKey().equals(pv.getPrivleageName())) {
                score = Double.parseDouble(pv.getPrivilegeValue());
                break;
            }
        }
        //有利润可以扣减
        if (profitRate != null && profitRate > 0) {
            Long serviceBalance = 0L;
            log.info("\n===========有利润可以扣减：{}==========", profitRate);
            CustomerFundVo fundVo = new CustomerFundVo();
            fundVo.setPlatformUid(customer.getPlatformUid());
            fundVo.setBizTime(date);
            fundVo.setBizNo(orderInfo.getOrderNo());
            fundVo.setOrderUid(orderInfo.getOrderUid());
            fundVo.setRemark("订单退款扣减收益和积分等");
            if (sale != null) {
                fundVo.setItemUid(sale.getItemUid());
                fundVo.setRemark(fundVo.getRemark() + ":" + sale.getItem().getProName());
                serviceBalance = sale.getServiceBalance();
            } else {
                fundVo.setRemark(fundVo.getRemark() + ":" + orderInfo.getItemList().get(0).getProName());
            }

            fundVo.setFromCustomerId(fromUserId);
            fundVo.setCustomerUid(customer.getCustomerUid());
            //默认一块钱一积分，可以根据店铺设置再优化
            Long goodsIntegral = 1L;
            PlatformGeneralsettingsVo data = platformGeneralsettingsService.get(customer.getPlatformUid());
            if (ObjectUtil.isNotEmpty(data)) {
                //一块钱对应多少积分
                goodsIntegral = Long.parseLong(data.getGoodsIntegral());
                if (ObjectUtil.isEmpty(goodsIntegral)) goodsIntegral = 1L;
            }
            fundVo.setScore(new Double(score * (refundAmount + serviceBalance * 0.01) * goodsIntegral).longValue());
            fundVo.setProfit(new Double(profitRate * 0.01 * refundAmount).longValue());
            fundVo.setStatus(CustomerFundStatusEnum.freeze.getKey());
            if (fundVo.getProfit() > 0 || fundVo.getScore() > 0) {
                int i = iCustomerFundService.deductionCustomerFund(fundVo);
                log.info("\n==========退款扣减收益和积分,parameter:{}==========\n===========result:{}===========\n",
                        JSONObject.toJSONString(fundVo), JSONObject.toJSONString(i));
            }
            return true;
        }
        return false;
    }

    /**
     * 用户同意处理
     *
     * @param query
     * @return
     */
    @Override
    public boolean agreeFinish(PostSaleQuery query) {
        String key = ORDER_POST_SALE_KEY + query.getServiceUid();
        limitUserOperation(key);

        if (ObjectUtil.isEmpty(query.getServiceUid()))
            throw new BaseException("售后ID不能为空");

        OrderPostSale postSale = this.getById(query.getServiceUid());
        if (postSale == null)
            throw new BaseException("没有找到售后信息");

        if (ServiceStatusEnum.agree.getKey().equals(postSale.getDataStatus())
                || ServiceStatusEnum.refuse.getKey().equals(postSale.getDataStatus())) {

            postSale.setDataStatus(ServiceStatusEnum.success.getKey());
            this.updateById(postSale);
            //记录流程节点
            saveSaleNode(postSale.getServiceUid(), postSale.getDataStatus(), "用户：" + SecurityUtils.getCustomerUserName() + " 同意完结该售后",
                    SecurityUtils.getCustomerUid(), SecurityUtils.getCustomerUserName(), new Date());

            OrderInfoItem item = itemService.getById(postSale.getItemUid());
            if (item == null)
                throw new BaseException("没有找到订单信息");
            item.setSaleStatus(SaleStatusEnum.end.getKey());
            itemService.updateById(item);

        } else {
            throw new BaseException("无法修改该售后信息");
        }


        return true;
    }

    /**
     * 用户退换货单号
     *
     * @param query
     * @return
     */
    @Override
    public boolean addLogistic(PostSaleQuery query) {
        String key = ORDER_POST_SALE_KEY + query.getServiceUid();
        limitUserOperation(key);

        if (ObjectUtil.isEmpty(query.getServiceUid()))
            throw new BaseException("订单售后ID不能为空");
        if (ObjectUtil.isEmpty(query.getLogisticsNo()))
            throw new BaseException("快递单号不能为空");

        OrderPostSale postSale = this.getById(query.getServiceUid());
        if (postSale == null)
            throw new BaseException("没有找到订单售后信息！");

        postSale.setLogisticsNo(query.getLogisticsNo());

        saveSaleNode(postSale.getServiceUid(), postSale.getDataStatus(), "用户：" + SecurityUtils.getCustomerUserName() + " 添加了快递单号",
                SecurityUtils.getCustomerUid(), SecurityUtils.getCustomerUserName(), new Date());

        return this.save(postSale);
    }

    /**
     * 审核
     *
     * @param sale
     * @return
     */
    @Override
    
    public boolean auditSale(OrderPostSale sale) {
        //用户层面限流
        String key = ORDER_POST_SALE_KEY + sale.getServiceUid();
        limitUserOperation(key);

        if (ObjectUtil.isEmpty(sale.getServiceUid()))
            throw new BaseException("售后ID不能为空");

        Date date = DateUtil.date();
        Long accountUid = SecurityUtils.getUserId();
        String accountName = SecurityUtils.getUsername();

        OrderPostSale postSale = this.getById(sale.getServiceUid());
        if (postSale == null) throw new BaseException("没有找到售后信息");

        postSale.setServiceCash(sale.getServiceCash());
        postSale.setServiceBalance(sale.getServiceBalance());

        postSale.setDataStatus(sale.getDataStatus());
        postSale.setRemark(sale.getRemark());
        postSale.setUpdateUser(accountUid);
        postSale.setUpdateName(accountName);
        postSale.setUpdateTime(date);


        if (ServiceStatusEnum.agree.getKey().equals(sale.getDataStatus())) {

            OrderInfo orderInfo = orderInfoService.getById(postSale.getOrderUid());
            if (orderInfo == null) throw new BaseException("没有找到订单信息");

            OrderInfoParent parent = parentService.getOrderInfo(orderInfo.getParentOrderNo());
            if (parent == null) throw new BaseException("没有找到订单支付信息");

            //退款,同意之后进行退款，完结售后
            if (ServiceTypeEnum.refund.getKey().equals(postSale.getServiceType())) {
                OrderInfoItem item = itemService.getById(postSale.getItemUid());
                if (item != null) {
                    postSale.setItem(item);
                    //微信退款==================
                    startRefund(postSale, orderInfo, parent);

                    postSale.setDataStatus(ServiceStatusEnum.success.getKey());
                    //完结
                    itemService.finishSale(postSale.getItemUid());

                    //退款数日志
                    orderInfoService.sendLogMsg(ProductOptType.refund.getKey(), orderInfo.getPlatformUid(), orderInfo.getCustomerUid(),item.getOrderType(), item.getProUid(), Convert.toLong(postSale.getServiceNumber()));
                } else
                    throw new BaseException("没有找到订单商品信息！");
            } else if (ServiceTypeEnum.returnd.getKey().equals(postSale.getServiceType())) {
                //退货退款，商家确认收货后，发起退款，完结
            } else {
                //换货，商家确认收货后，完结
            }
        }

        this.updateById(postSale);
        //记录流程节点
        saveSaleNode(postSale.getServiceUid(), postSale.getDataStatus(),
                "商家：" + accountName + "," + ServiceStatusEnum.getNameByKey(postSale.getDataStatus()),
                accountUid, accountName, date);

        return true;
    }

    /**
     * 开始退款流程
     *
     * @param postSale
     * @param orderInfo
     * @param parent
     */
    private void startRefund(OrderPostSale postSale, OrderInfo orderInfo, OrderInfoParent parent) {

        OrderPayInfo payInfo = payInfoService.getOrderPayInfo(parent.getParentOrderNo(), parent.getPayMethod());
        if (ObjectUtil.isNotNull(payInfo) && ObjectUtil.isNotEmpty(payInfo.getSubMchid())) {

            boolean b = wechatRefund(parent, orderInfo, postSale, payInfo.getSubMchid());

            if (!b) throw new BaseException("微信退款失败！");
        } else
            throw new BaseException("没有找到微信支付信息");
    }

    /**
     * 用户所有退款信息
     *
     * @param itemUid
     * @return
     */
    @Override
    public List<OrderPostSaleVo> getOrderRefund(Long itemUid) {

        return orderPostSaleMapper.getOrderRefund(itemUid);
    }

    @Override
    public Integer getOrderRefundCount(Long itemUid) {
        List<OrderPostSaleVo> list = orderPostSaleMapper.getOrderRefund(itemUid);
        if (ObjectUtil.isNotEmpty(list))
            return list.size();
        return 0;
    }

    @Override
    public List<ProductOptVo> getOptCount(CustomerGroupDefinitionQuery query) {
        return orderPostSaleMapper.getOptCount(query);
    }


    private void saveSaleNode(Long serviceUid, String nodeStatus, String nodeDesc, Long createUser, String createName, Date createTime) {
        OrderPostSaleNode saleNode = new OrderPostSaleNode(serviceUid, nodeStatus, nodeDesc, createUser, createName, createTime);
        saleNodeService.save(saleNode);
    }

    /**
     * 限制用户对订单的操作频率
     */
    private void limitUserOperation(String key) {
        if (redisService.incr(key, USER_OPERATOR_LIMIT_TIME) > USER_OPERATOR_LIMIT)
            throw new BaseException(MessageConstants.MSG_FAST);
    }

}
